﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.IO;

namespace CDDocumentExtractor
{
    public class CaseDocument
    {
        public string RegEx_ManuID = "MANU\\x2F\\w*\\x2F\\d*\\x2F\\d{4}";

        // Single Value Tags
        public string _ManuID = "";
        public string _InfoOneID = "";
        public string _DocumentData = "";
        public bool LinkParsingRequired = false;

        // delegate declaration 
        public delegate void MessageSentHandler(string msg);

        // event declaration 
        public event MessageSentHandler MessageSent; 

        public string _Title = "";
        public DateTime _DecidedOn;
        private string _AppealNo = "";
        private string _Subject = "";
        private string _EquivalentCitation = "";

        public string PDFFilePath = "";
        public string PDFSectionFilePath = "";
        public string DOCXFilePath = "";
        public int DocumentID = 0;
        private int ContentID = 0;
        public string CitingRefData_XML = "";


        //Multiple Value Tags
        private List<string> _Appellants = new List<string>();
        private List<string> _Respondents = new List<string>();
        private List<string> _Judges = new List<string>();
        private List<string> _CasesReferred = new List<string>();
        private List<string> _NotifyCitations = new List<string>();
        private List<string> _CounselSSAs = new List<string>();
        private List<string> _CounselSAs = new List<string>();
        private List<string> _CounselSRs = new List<string>();
        private List<string> _ActRuleOrders = new List<string>();
        private List<string> _AuthoritiesRefereds = new List<string>();
        private List<clsCitingReference> _CitingRefs = new List<clsCitingReference>();
        private List<string> _PriorHistories = new List<string>();
        private List<string> _CaseNotes = new List<string>();

        //Combination of Appelant and Respondants
        private List<AppelantRespondant> _AppelantRespondants = new List<AppelantRespondant>();

        private List<string> _LinkRelations = new List<string>();

        /// <summary>
        /// Converted HTML with all the tags information removed. 
        /// This can further be processed very easily to remove links
        /// </summary>
        public string InfoOneDocumentData = "";

        private string _RatioDecidendid=string.Empty;
        private string _Desposition = string.Empty;
        public string HTMLFilePath;
        public int _DocumentSectionID;
        public string InfoOneCitationNo;

        private string GetCombinedValues(List<string> items)
        {
            var sb = new StringBuilder();

            foreach (var item in items)
            {
                sb.Append(item);
                sb.Append("||");
            }

            if (sb.Length > 2)
                return sb.ToString().Substring(0, sb.Length - 2);

            return sb.ToString();
        }

        public CaseDocument(string DocumentData)
        {
            _DocumentData = DocumentData;

            Process();
        }

        public void Process()
        {
            this._ManuID = this.GetTagValue("manuid");
            this._Title = this.GetTagValue("title");
            this._AppealNo = this.GetTagValue("appealno");
            var temp = this.GetTagValue("decidedon");

            if (temp.StartsWith("00"))
                temp = "01.01." + this._ManuID.Substring(this._ManuID.Length - 4, 4);

            var Date_parts = temp.Split('.', '/', '-', ' ');

            if (Date_parts.Length >= 3)
                this._DecidedOn = new DateTime(Convert.ToInt32(Date_parts[2]), Convert.ToInt32(Date_parts[1]), Convert.ToInt32(Date_parts[0]));
            else
                this._DecidedOn = DateTime.Now;

            this._Subject = this.GetTagValue("subject");

            this._Appellants = this.GetTagValues("appellant");
            this._Respondents = this.GetTagValues("respondent");

            FillAppelantRespondants();

            this._Judges = this.GetTagValues("judge");
            //Remove 
            for (int i = 0; i < _Judges.Count; i++)
            {
                var val = _Judges[i].Trim();
                if (val.ToLower() == "jj.")
                    val = "";

                if (val.ToLower() == "jj")
                    val = "";

                if (val.ToLower() == "jj .")
                    val = "";
                
                if (val.ToLower() == ",")
                    val = "";

                _Judges[i] = val;
            }
            _Judges.RemoveAll(jn => jn.Trim().Length <= 0);

            this._Desposition = this.GetTagValue("desposition");
            this._RatioDecidendid = this.GetTagValue("ratiodecidendi");
            this._CasesReferred = this.GetTagValues("casesrefered");
            this._NotifyCitations = this.GetTagValues("nfcitation");

            this._CounselSSAs = this.GetTagValues("counselssa");
            this._CounselSAs = this.GetTagValues("counselsa");
            this._CounselSRs = this.GetTagValues("counselsr");
            this._ActRuleOrders = this.GetTagValues("actruleorder");
            this._AuthoritiesRefereds = this.GetTagValues("authoritiesrefered");

            var citingData = this.GetTagValues("citingref");
            if (citingData.Count > 0)
            {
                this._CitingRefs.AddRange(ProcessCitingReferences(citingData[0].ToString()));
                this.CitingRefData_XML = GetCitingRefData_XML(ProcessCitingReferences(citingData[0].ToString()));
            }

            this._PriorHistories = this.GetTagValues("priorhistory");
            this._CaseNotes = this.GetTagValues("casenote");

            //Get Equivalant Citation detail which is non RegEX search
            this._EquivalentCitation = GetEquivalantCitations();

            //Extract InfoOne Specific Document.
            this.InfoOneDocumentData = GetJudgementDetail();

            //Get List of all links this will server two purposes.
            // 1. If Link Parsing required 
            // 2. List of Related Documents
            this._LinkRelations = this.GetTagValues("a", this.InfoOneDocumentData);

            //Code below will remove any extra text from the link text and provide only manu ids
            for (int i = 0; i < this._LinkRelations.Count; i++)
            {
                System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(RegEx_ManuID, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
                var match = rx.Match(this._LinkRelations[i]);

                if (match.Success)
                    this._LinkRelations[i] = match.Value;
            }

            this.LinkParsingRequired = this._LinkRelations.Count > 0;
        }


        private List<clsCitingReference> ProcessCitingReferences(string data)
        {
            List<clsCitingReference> list = new List<clsCitingReference>();
            List<string> ss = new List<string>();
            ss.Add("\r\n");
            var processedData = data.Split(ss.ToArray(), StringSplitOptions.RemoveEmptyEntries);

            ss.Clear();
            ss.Add("\t");
            foreach (var item in processedData)
            {
                var txt = item.Split(ss.ToArray(), StringSplitOptions.RemoveEmptyEntries);
                var clsItem = new clsCitingReference();

                if (txt.Length > 0)
                    clsItem.citingReference = txt[0].Trim();

                if (txt.Length > 1)
                    clsItem.ReferenceStatus = txt[1].Trim();

                list.Add(clsItem);
            }

            return list;
        }

        private string RemoveNonMANULinks(string finalData)
        {
            string exp = "<a\\b[^>]*>(.*?)</a>";
            System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(exp, System.Text.RegularExpressions.RegexOptions.IgnoreCase);

            var matchEval = new System.Text.RegularExpressions.MatchEvaluator(NonMANULinkReplacementString);
            return rx.Replace(finalData, matchEval);
        }

        //Return non HTML values if it doesn't contain MANU links. For Manu Links there would be a different treatment.
        public static string NonMANULinkReplacementString(System.Text.RegularExpressions.Match match)
        {
            //Check if it contains manu link. if not return html scrapped values
            if (!match.Value.Contains("'MANU/"))
            {
                return System.Text.RegularExpressions.Regex.Replace(match.Value, "<.*?>", string.Empty);
            }
            //else return actual value
            return match.Value;
        }

        //This will return Equivalant Citations Detail from the Document
        public string GetEquivalantCitations()
        {
            // == Document Details Here
            List<string> values = GetTags("p");

            foreach (var item in values)
            {
                //Start of Document
                if (item.ToLower().Contains("equivalent citation"))
                {
                    return System.Text.RegularExpressions.Regex.Replace(item, "<.*?>", string.Empty).Replace("Equivalent Citation:", "").Trim();
                }
            }
            return "";
        }

        public string GetJudgementDetail()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<HTML>");
            sb.AppendLine("    <HEAD>");
            sb.AppendLine("        <TITLE>" + this._Title + "</TITLE>");
            sb.AppendLine("    </HEAD>");
            sb.AppendLine("    <BODY>");

            // == Document Details Here
            List<string> values = GetTags("p");
            //<p class="centerAlign"><b>JUDGMENT</b></p>
            bool somethingFound = false;


            var logFile = WebUtility.LogFileIfNoJudgement;

            bool startCapturing = false;
            foreach (var item in values)
            {
                //If not capturing check if capturing should start
                if (!startCapturing)
                {
                    //Start of Document
                    if (item.ToLower().Contains("centeralign") &&
                        (item.ToLower().Contains("judgment") || item.ToLower().Contains("order")))
                    {
                        startCapturing = true;
                        somethingFound = true;
                    }
                }

                //if capturing check if capturing should be blocked
                if (startCapturing)
                {
                    //End of Document
                    if (item.ToLower().Contains("manupatra information solutions"))
                    {
                        startCapturing = false;
                    }
                }

                if (startCapturing)
                {
                    sb.AppendLine("        " + item.Trim());
                }
            }

            if (!somethingFound)
                 File.AppendAllText(WebUtility.LogFileIfNoJudgement,this._ManuID + Environment.NewLine);

            sb.AppendLine("    </BODY>");
            sb.AppendLine("</HTML>");

            //Remove Non Manu Links first before getting final Document Data.
            return RemoveNonMANULinks(sb.ToString());
        }

        public string GetTagValue(string tag)
        {
            //string exp = "<" + tag + "\\b[^>]*>(.*?)</" + tag + ">";
            string exp = "<" + tag + "[^>]*>(.*?)</" + tag + ">";
            System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(exp, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
            var match = rx.Match(this._DocumentData);
            if (match.Success)
                return System.Text.RegularExpressions.Regex.Replace(match.Value, "<.*?>", string.Empty);
            else
                return "";
        }

        public List<string> GetTagValues(string tag)
        {
            return GetTagValues(tag, this._DocumentData);
        }

        public string RemoveHTMLTags(string value)
        {
            return System.Text.RegularExpressions.Regex.Replace(value, "<.*?>", string.Empty);
        }

        public List<string> GetTagValues(string tag, string DataToCheck)
        {
            //string exp = "<" + tag + "\\b[^>]*>(.*?)</" + tag + ">";
            string exp = "<" + tag + "[^>]*>(.*?)</" + tag + ">";
            List<string> list = new List<string>();
            System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(exp, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);

            var matches = rx.Matches(DataToCheck);
            foreach (System.Text.RegularExpressions.Match match in matches)
            {
                string val = System.Text.RegularExpressions.Regex.Replace(match.Value, "<.*?>", string.Empty);
                if (val.Trim().Length > 0)
                {
                    string parsedValue = val.Trim();
                    int i = 0;
                    while (i<10 && (parsedValue.EndsWith(",") || parsedValue.EndsWith("and")))
                    {
                        
                        if (parsedValue.EndsWith(","))
                        {
                            parsedValue = parsedValue.Length > 1 ? parsedValue.Substring(0, parsedValue.Length - 1) : parsedValue;
                        }

                        if (parsedValue.EndsWith("and"))
                        {
                            parsedValue = parsedValue.Length > 3 ? parsedValue.Substring(0, parsedValue.Length - 3) : parsedValue;
                        }
                        i++;
                    }

                    list.Add(parsedValue);
                }
            }

            return list;
        }

        public List<string> GetTags(string tag)
        {
            //string exp = "<" + tag + "\\b[^>]*>(.*?)</" + tag + ">";
            string exp = "<" + tag + "[^>]*>(.*?)</" + tag + ">"; //<citingref[^>]*>(.*?)</citingref>
            List<string> list = new List<string>();
            System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(exp, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);

            var matches = rx.Matches(this._DocumentData);
            foreach (System.Text.RegularExpressions.Match match in matches)
            {
                list.Add(match.Value);
            }

            return list;
        }

        //This method will process all the links in the document. Update them and regenerate pdf and docx files
        public bool Save(string docxpath, string pdfPath)
        {
            //If Link Parsing Required
            if (this.LinkParsingRequired)
            {
                using (var db = new I1DBModelDataContext())
                {
                    var list = from ds in db.DocumentMetas
                               where this._LinkRelations.Contains(ds.ManupatraCitation)
                               select new
                               {
                                   InfoOneID = ds.DocumentID,
                                   InfoOneCitation = ds.InfoOneCitation,
                                   ManupatraCitation = ds.ManupatraCitation
                               };

                    var listDocs = list.ToList();

                    //if count is equal means we have all the document ids to update the links.
                    //otherwise just skip this step
                    if (listDocs.Count == this._LinkRelations.Count)
                    {

                    }
                }
            }

            this.DOCXFilePath = docxpath;
            this.PDFFilePath = pdfPath;

            SaveDocument();

            return true;
        }

        public bool Save()
        {
            string strJudges = GetCombinedValues(this._Judges);
            string strAppelants = GetCombinedValues(this._Appellants);
            string strRespondents = GetCombinedValues(this._Respondents);

            string strLawyerAppelant = GetCombinedValues(this._CounselSAs);
            string strLawyerRespondent = GetCombinedValues(this._CounselSRs);
            string strLawyerCommons = GetCombinedValues(this._CounselSSAs);

            string strNotifyCitations = GetCombinedValues(this._NotifyCitations);
            string strAuthoritiesRefereds = GetCombinedValues(this._AuthoritiesRefereds);

            DateTime currentDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            string _Remarks = "Bulk Import";

            using (var db = new I1DBModelDataContext())
            {
                using (var tScope = new System.Transactions.TransactionScope())
                {

                    var task = new Task();
                    task.Notes = _Remarks;
                    task.AssignedTo = 1;
                    task.TaskType = 1;
                    task.CompletionDate = currentDate;
                    task.CreatedBy = 1;
                    task.CreatedDate = currentDate;

                    var s1 = new TaskStatus();
                    s1.Status = 0;      //Open Status
                    s1.Remarks = _Remarks;
                    s1.CreatedBy = 1;
                    s1.CreatedDate = currentDate;
                    task.TaskStatus.Add(s1);

                    s1 = new TaskStatus();
                    s1.Status = 1;      //Submit for review
                    s1.Remarks = _Remarks;
                    s1.CreatedBy = 1;
                    s1.CreatedDate = currentDate;
                    task.TaskStatus.Add(s1);

                    s1 = new TaskStatus();
                    s1.Status = 2;      //Approved
                    s1.Remarks = _Remarks;
                    s1.CreatedBy = 1;
                    s1.CreatedDate = currentDate;
                    task.TaskStatus.Add(s1);

                    s1 = new TaskStatus();
                    s1.Status = 5;      //Published
                    s1.Remarks = _Remarks;
                    s1.CreatedBy = 1;
                    s1.CreatedDate = currentDate;
                    task.TaskStatus.Add(s1);

                    //Save Task into Database
                    db.Tasks.InsertOnSubmit(task);
                    db.SubmitChanges();

                    var doc = new DocumentMaster();
                    doc.DocumentID = task.TaskID;

                    if (this._Appellants.Count > 0 && this._Respondents.Count > 0)
                        doc.Name = this._Appellants[0].Trim() + " V. " + this._Respondents[0].Trim();
                    else
                        doc.Name = this._Title;

                    doc.Name = TrimStringIfRequired(doc.Name,1500);
                    doc.Notes = _Remarks;// this.LinkParsingRequired ? _Remarks : "";
                    //extract first 250 chars
                    var descr = RemoveHTMLTags("" + InfoOneDocumentData).Trim();
                    if (descr.Length > 250)
                        descr = descr.Substring(0, 250);
                    doc.Description = descr;

                    doc.IsPublished = !this.LinkParsingRequired;
                    doc.CreatedBy = 1;
                    doc.CreatedDate = currentDate;
                    doc.ModifiedBy = 1;
                    doc.ModifiedDate = currentDate;
                    doc.StatusUpdatedBy = 1;
                    doc.StatusUpdateDate = currentDate;
                    doc.IsDisable = false;
                    doc.IsBlank = false;
                    doc.StatusSNo = 0;
                    
                    task.DocumentMasters.Add(doc);

                    //Save multiple equivalant citations as other citations
                    if (this._EquivalentCitation.Length > 0)
                    {
                        var citas = this._EquivalentCitation.Split(',');
                        foreach (var item in citas)
                        {
                            //Save Equivalant Citations
                            var docCitations = new DocumentOtherCitation();
                            docCitations.CitationCompany = "Other";
                            docCitations.CitationNo = item;
                            doc.DocumentOtherCitations.Add(docCitations);
                        }
                    }

                    //Save Task into Database
                    //db.Tasks.InsertOnSubmit(task);
                    db.SubmitChanges();

                    DocumentID = doc.DocumentID;

                    foreach (var item in this._Judges)
                    {
                        var ln = new JudgesName();
                        ln.DocumentId = doc.DocumentID;
                        ln.IsPrimary = true;
                        ln.JudgesNames = TrimStringIfRequired(item,2000);
                        db.JudgesNames.InsertOnSubmit(ln);
                    }

                    foreach (var item in this._CounselSAs)
                    {
                        var ln = new LawyerName();
                        ln.DocumentId = doc.DocumentID;
                        ln.LawyerNames = TrimStringIfRequired(item,2000);
                        db.LawyerNames.InsertOnSubmit(ln);
                    }

                    foreach (var item in this._CounselSRs)
                    {
                        var ln = new RespondantLawyer();
                        ln.DocumentId = doc.DocumentID;
                        ln.LawyerNames = TrimStringIfRequired(item,2000);
                        db.RespondantLawyers.InsertOnSubmit(ln);
                    }

                    foreach (var item in this._AppelantRespondants)
                    {
                        var ln = new DocumentAppellantRespondent();
                        ln.DocumentID = doc.DocumentID;
                        ln.IsPrimary = item.IsPrimary;
                        ln.Appellant = TrimStringIfRequired(item.Appelant,1000);
                        ln.Respondent = TrimStringIfRequired(item.Respondant,1000);
                        db.DocumentAppellantRespondents.InsertOnSubmit(ln);
                    }

                    //Update Document Published PDF Paths
                    //doc.Path = "PublishedDocs/" + currentDate.Month.ToString() + currentDate.Year.ToString() + "/SectionDocs/" + doc.DocumentID.ToString() + "/Doc_" + doc.DocumentID.ToString() + ".pdf";
                    doc.Path = "PublishedDocs/" + doc.DocumentID.ToString() + "/Doc_" + doc.DocumentID.ToString() + ".pdf";
                    this.PDFFilePath = doc.Path;

                    //Perform Update Operations
                    var docMeta = new DocumentMeta();
                    docMeta.DocumentType = 1;
                    docMeta.AuthorityCheck = TrimStringIfRequired(GetCombinedValues(this._AuthoritiesRefereds),8000);
                    docMeta.DocumentTitle = doc.Name;
                    docMeta.DocumentDesc = doc.Name;
                    docMeta.DocumentIssueDate = this._DecidedOn;
                    docMeta.DocumentEnfDate = this._DecidedOn;
                    docMeta.AmendmendDate = this._DecidedOn;
                    docMeta.DocumentStatus = 0;
                    //docMeta.CaseNote = ""; 
                    docMeta.JudgesNames = TrimStringIfRequired(strJudges,8000);//.Substring(0, 30);
                    docMeta.Bench = this._Judges.Count;
                    docMeta.Juridiction = Convert.ToInt32(Program.Juridiction);// 2;        //1 SC,    2 HC,    3 TC
                    docMeta.CourtNameId = Convert.ToInt32(Program.CourtNameId);// 4;        //Supreme Court
                    docMeta.LawyersNames = TrimStringIfRequired(strLawyerAppelant,8000);
                    docMeta.RespondantLawyers = TrimStringIfRequired(strLawyerRespondent,8000);
                    docMeta.CommonLawyers = strLawyerCommons;

                    docMeta.PetitionNo = this._AppealNo;
                    docMeta.StatusChangeDate = currentDate;
                    docMeta.IssueYear = this._DecidedOn.Year;
                    docMeta.TypeOfLawID = "";
                    docMeta.JudgementDate = this._DecidedOn;
                    docMeta.IsPrimary = true;
                    docMeta.PriorHistory = TrimStringIfRequired(GetCombinedValues(this._PriorHistories),8000);
                    docMeta.ManupatraCitation = this._ManuID;
                    docMeta.CasesRefferedto = GetCombinedValues(this._CasesReferred);
                    docMeta.ActsReffered = GetCombinedValues(this._ActRuleOrders);
                    docMeta.DocumentID = doc.DocumentID;
                    docMeta.EquivalentCitation = this.LinkParsingRequired ? "PRC" : "";
                    docMeta.CaseNote_M = GetCombinedValues(this._CaseNotes); //this._Subject;
                    docMeta.CaseNote_I = this._Subject;  //"InfoOne";  //this will be used to update TypeofLawID
                    docMeta.StatusChangeDate = currentDate;

                    docMeta.Disposition = this._Desposition;
                    docMeta.Ratiodecidendi = this._RatioDecidendid;
                    doc.DocumentMetas.Add(docMeta);

                    var docSection = new DocumentSection();
                    docSection.DocumentID = doc.DocumentID;
                    docSection.SectionName = doc.Name;
                    docSection.SectionCopyName = "";
                    docSection.Sequence = 1;
                    doc.DocumentSections.Add(docSection);

                    //db.Log = Console.Out;

                    db.SubmitChanges();

                    //docSection.Path = "CurrentDocuments/" + currentDate.Month.ToString() + currentDate.Year.ToString() + "/SectionDocs/" + doc.DocumentID.ToString() + "/" + docSection.SectionID.ToString() + ".docx";
                    //docSection.PublishedPath = "PublishedDocs/" + currentDate.Month.ToString() + currentDate.Year.ToString() + "/SectionDocs/" + doc.DocumentID.ToString() + "/" + docSection.SectionID.ToString() + ".Pdf";
                    docSection.Path = "CurrentDocuments/" + doc.DocumentID.ToString() + "/" + docSection.SectionID.ToString() + ".docx";
                    docSection.PublishedPath = "PublishedDocs/" + doc.DocumentID.ToString() + "/" + docSection.SectionID.ToString() + ".Pdf";

                    this.DOCXFilePath = docSection.Path;
                    this.PDFSectionFilePath = docSection.PublishedPath;

                    db.SubmitChanges();

                    ////Updating Citing references
                    //foreach (var item in this._CitingRefs)
                    //{
                    //    var ln = new CitingReference();
                    //    ln.CaseReffered = TrimStringIfRequired(item.citingReference, 2500);
                    //    ln.CaseStatus = item.ReferenceStatus;
                    //    db.CitingReferences.InsertOnSubmit(ln);
                    //    db.SubmitChanges();

                    //    ln.DocumentRelations.Add(new DocumentRelation()
                    //    {
                    //        DocumentID = DocumentID,
                    //        IsPublished = true,
                    //        Createdby = 1,
                    //        CitingRefereneID = ln.ReferenceID,
                    //        CreatedDate = currentDate
                    //    });
                    //    db.SubmitChanges();
                    //}

                    tScope.Complete();
                }
            }

            //Only write Word/PDF if link parsing is not required. 
            //Otherwise Word/PDF will be written after link parsing
            if (!this.LinkParsingRequired)
                this.SaveDocument();

            return true;
        }

        public bool SaveBySP()
        {
            string strJudges = GetCombinedValues(this._Judges);
            string strAppelants = GetCombinedValues(this._Appellants);
            string strRespondents = GetCombinedValues(this._Respondents);

            string strLawyerAppelant = GetCombinedValues(this._CounselSAs);
            string strLawyerRespondent = GetCombinedValues(this._CounselSRs);
            string strLawyerCommons = GetCombinedValues(this._CounselSSAs);

            string strNotifyCitations = GetCombinedValues(this._NotifyCitations);
            string strAuthoritiesRefereds = GetCombinedValues(this._AuthoritiesRefereds);

            DateTime currentDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            string _Remarks = "Bulk Import";

            using (var con = new SqlConnection(new I1DBModelDataContext().Connection.ConnectionString))
            {
                var com = con.CreateCommand();
                com.CommandType = CommandType.StoredProcedure;
                com.CommandText = "sp_AddManuDoc";

                var parm = new SqlParameter
                               {
                                   Direction = ParameterDirection.Input,
                                   SqlDbType = SqlDbType.VarChar,
                                   ParameterName = "@Name",
                                   Size = 1500,
                                   Value = this._Title
                               };
                com.Parameters.Add(parm);
                if (this._Appellants.Count > 0 && this._Respondents.Count > 0)
                    parm.Value = this._Appellants[0].Trim() + " V. " + this._Respondents[0].Trim();
                else
                    parm.Value = this._Title;
                parm.Value = TrimStringIfRequired(parm.Value.ToString(), 1500);

                
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@Description",
                    Value = ""
                };
                com.Parameters.Add(parm);
                var descr = RemoveHTMLTags("" + InfoOneDocumentData).Trim();
                if (descr.Length > 250)
                    descr = descr.Substring(0, 250);
                parm.Value = descr;


                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@Remarks",
                    Value = _Remarks
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@IsPublished",
                    Value = !LinkParsingRequired
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@EquivalentCitation",
                    Value = this._EquivalentCitation
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@Judges",
                    Size = 8000,
                    Value = TrimStringIfRequired(strJudges, 8000)
                };
                com.Parameters.Add(parm); 
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.Int,
                    ParameterName = "@JudgesCount",
                    Size = 8000,
                    Value = this._Judges.Count
                };
                com.Parameters.Add(parm); 
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@LawyerNames",
                    Value = strLawyerAppelant
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@RespondantLawyers",
                    Value = strLawyerRespondent
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@CommonLawyers",
                    Value = strLawyerCommons
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.Xml,
                    ParameterName = "@DocumentAppellantRespondents",
                    Value = GetCombinedAppelantRespondants()
                };
                com.Parameters.Add(parm);
                
                if (string.IsNullOrEmpty(parm.Value.ToString().Trim()))
                    parm.Value = null;

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@AuthorityCheck",
                    Value = TrimStringIfRequired(GetCombinedValues(this._AuthoritiesRefereds), 8000)
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.DateTime,
                    Size = 8000,
                    ParameterName = "@DecidedOn",
                    Value = this._DecidedOn
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.Int,
                    ParameterName = "@CourtType",
                    Value = Program.Juridiction
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.Int,
                    ParameterName = "@CourtID",
                    Value = Program.CourtNameId
                };
                com.Parameters.Add(parm); 
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@PetitionNo",
                    Value = _AppealNo
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@TypeOfLaw",
                    Value = this._Subject
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@PriorHistory",
                    Value = TrimStringIfRequired(GetCombinedValues(this._PriorHistories), 8000)
                };
                com.Parameters.Add(parm); parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@ManupatraCitation",
                    Value = _ManuID
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Size = 8000,
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@CasesRefferedto",
                    Value = GetCombinedValues(this._CasesReferred)
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@ActsReffered",
                    Value = GetCombinedValues(this._ActRuleOrders)
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Size = 8000,
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.Bit,
                    ParameterName = "@LinkParsing",
                    Value = !LinkParsingRequired?1:0
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Size = 8000,
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@CaseNotes",
                    Value = GetCombinedValues(this._CaseNotes)
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@Subject",
                    Value = this._Subject                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 8000,
                    ParameterName = "@Disposition",
                    Value = this._Desposition
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@Ratiodecidendi",
                    Value = this._RatioDecidendid
                };
                com.Parameters.Add(parm);
                parm = new SqlParameter
                {
                    Size = 8000,
                    Direction = ParameterDirection.Input,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@SavingFolder",
                    Value = "121901"
                };
                com.Parameters.Add(parm);
               
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Input,
                    Size = 8000,
                    SqlDbType = SqlDbType.Xml,
                    ParameterName = "@CitingRefData",
                    Value = CitingRefData_XML//.Length>0? CitingRefData_XML:null
                };
                com.Parameters.Add(parm);

                //=====================================================
                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Output,
                    SqlDbType = SqlDbType.Int,
                    Size = 8000,
                    ParameterName = "@Out_DocumentID"
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Size = 8000,
                    Direction = ParameterDirection.Output,
                    SqlDbType = SqlDbType.Int,
                    ParameterName = "@Out_SectionID"
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Size = 8000,
                    Direction = ParameterDirection.Output,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@Out_InfoOneCitatonNo"
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Output,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@Out_Path"
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Output,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@Out_PdfPath"
                };
                com.Parameters.Add(parm);

                parm = new SqlParameter
                {
                    Direction = ParameterDirection.Output,
                    Size = 8000,
                    SqlDbType = SqlDbType.VarChar,
                    ParameterName = "@Out_HtmlPath"
                };
                com.Parameters.Add(parm);
                
                con.Open();
                using (var scope = new System.Transactions.TransactionScope())
                {
                    com.ExecuteNonQuery();
                    scope.Complete();

                    this._InfoOneID = Convert.ToInt32(com.Parameters["@Out_DocumentID"].Value).ToString();
                    this._DocumentSectionID = (int)com.Parameters["@Out_SectionID"].Value;
                    this.InfoOneCitationNo = Convert.ToString(com.Parameters["@Out_InfoOneCitatonNo"].Value);

                    this.DOCXFilePath = Convert.ToString(com.Parameters["@Out_Path"].Value);
                    this.PDFFilePath = Convert.ToString(com.Parameters["@Out_PdfPath"].Value);
                    this.HTMLFilePath = Convert.ToString(com.Parameters["@Out_HtmlPath"].Value);
                }
            }

            //Only write Word/PDF if link parsing is not required. 
            //Otherwise Word/PDF will be written after link parsing
            //if (!this.LinkParsingRequired)
            this.SaveDocument();

            return true;
        }
        
        public string GetCombinedAppelantRespondants()
        {
            string abc = "<Data>";
            foreach (var item in this._AppelantRespondants)
            {
                abc += "<AP>";
                abc += "<IsPrimary><![CDATA[" + (item.IsPrimary ? 1 : 0) + "]]></IsPrimary>";
                abc += "<Appelant><![CDATA[" + TrimStringIfRequired(item.Appelant, 1000) + "]]></Appelant>";
                abc += "<Respondant><![CDATA[" + TrimStringIfRequired(item.Respondant, 1000) + "]]></Respondant>";
                abc += "</AP>";
            }
            abc += "</Data>";
            return abc;
        }

        public string GetCitingRefData_XML(List<clsCitingReference> processCitingReferences)
        {
            string abc = "<Data>";
            foreach (var item in processCitingReferences)
            {
                abc += "<CF>";
                var rx = new System.Text.RegularExpressions.Regex(RegEx_ManuID, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
                var match = rx.Match(item.citingReference);
                var manuID = "";
                item.citingReference = item.citingReference.Trim();

                if (match.Success)
                {
                    manuID = match.Value;
                    item.citingReference = item.citingReference.Replace(manuID, "");
                }

                if (item.ReferenceStatus.Trim().Length <= 0)
                    item.ReferenceStatus = "Mentioned";

                abc += "<Title>" + TrimStringIfRequired(item.citingReference, 1000) + "</Title>";
                abc += "<Status>" + TrimStringIfRequired(item.ReferenceStatus.Trim(), 50) + "</Status>";
                abc += "<ManuID>" + TrimStringIfRequired(manuID.Trim(), 100) + "</ManuID>";
                abc += "</CF>";
            }
            abc += "</Data>";
            
            return abc;
        }

        //Trim characters if required.
        private string TrimStringIfRequired(string strToTrim, int length)
        {
            if (strToTrim.Length > length)
                return strToTrim.Substring(0, length);

                return strToTrim;
        }

        public void SaveDocument()
        {
            var htmlPath = Path.Combine(WebUtility.DocumentsFolder.Replace("-main",""), this.HTMLFilePath);

            if (File.Exists(htmlPath))
                File.Delete(htmlPath);

            string dirName = Path.GetDirectoryName(htmlPath);
            if (!Directory.Exists(dirName))
                Directory.CreateDirectory(dirName);

            File.WriteAllText(htmlPath, this.InfoOneDocumentData);

            Aspose.Words.Document doc = new Aspose.Words.Document(htmlPath);
            doc.ViewOptions.ViewType = Aspose.Words.Settings.ViewType.PageLayout;
            
            foreach (Aspose.Words.Section item in doc.Sections)
            {
                item.PageSetup.TopMargin = 10;
                item.PageSetup.RightMargin = 10;
                item.PageSetup.BottomMargin = 10;
                item.PageSetup.LeftMargin = 10;

                foreach (Aspose.Words.Paragraph paras in item.Body.Paragraphs)
                {
                    paras.ParagraphFormat.Alignment = Aspose.Words.ParagraphAlignment.Justify;
                    paras.ParagraphFormat.Style.Font.Name = "Arial";
                }
            }

            string docxPath = Path.Combine(WebUtility.DocumentsFolder, this.DOCXFilePath);
            string pdfPath = Path.Combine(WebUtility.DocumentsFolder, this.PDFFilePath);
            string secpdfPath = Path.Combine(WebUtility.DocumentsFolder, this.PDFSectionFilePath);

            if (!Directory.Exists(Path.GetDirectoryName(docxPath)))
                Directory.CreateDirectory(Path.GetDirectoryName(docxPath));

            if (!Directory.Exists(Path.GetDirectoryName(pdfPath)))
                Directory.CreateDirectory(Path.GetDirectoryName(pdfPath));

            if (!Directory.Exists(Path.GetDirectoryName(secpdfPath)))
            Directory.CreateDirectory(Path.GetDirectoryName(secpdfPath));

            //Save to Docx
            Common.TryDelete(docxPath);
            doc.Save(docxPath, Aspose.Words.SaveFormat.Docx);

            //Save the PDF
            Common.TryDelete(pdfPath);
            doc.Save(pdfPath, Aspose.Words.SaveFormat.Pdf);
            
            //This will be created after the whole process
            //Save the Section PDF
            //Common.TryDelete(secpdfPath);
            //doc.Save(secpdfPath, Aspose.Words.SaveFormat.Pdf);
        }

        private void FillAppelantRespondants()
        {
            for (int i = 0; i < this._Appellants.Count; i++)
            {
                string appe = this._Appellants[i];
                string resp = this._Respondents.Count > i ? this._Respondents[i] : "";
                this._AppelantRespondants.Add(new AppelantRespondant()
                {
                    Appelant = appe,
                    Respondant = resp,
                    IsPrimary = this._Title.Contains(appe) && this._Title.Contains(resp)
                });
            }
        }
    }
}